﻿using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework.Graphics;
using Terraria.ID;

namespace Terraria.ModLoader
{
	// Token: 0x02000253 RID: 595
	public static class WallLoader
	{
		// Token: 0x060018EB RID: 6379 RVA: 0x00421414 File Offset: 0x0041F614
		internal static int ReserveWallID()
		{
			if (ModNet.AllowVanillaClients)
			{
				throw new Exception("Adding walls breaks vanilla client compatiblity");
			}
			int result = WallLoader.nextWall;
			WallLoader.nextWall++;
			return result;
		}

		// Token: 0x170001B9 RID: 441
		// (get) Token: 0x060018EC RID: 6380 RVA: 0x000122DA File Offset: 0x000104DA
		public static int WallCount
		{
			get
			{
				return WallLoader.nextWall;
			}
		}

		// Token: 0x060018ED RID: 6381 RVA: 0x000122E1 File Offset: 0x000104E1
		public static ModWall GetWall(int type)
		{
			if (type < 231 || type >= WallLoader.WallCount)
			{
				return null;
			}
			return WallLoader.walls[type - 231];
		}

		// Token: 0x060018EE RID: 6382 RVA: 0x0041E6B0 File Offset: 0x0041C8B0
		private static void Resize2DArray<T>(ref T[,] array, int newSize)
		{
			int length = array.GetLength(0);
			int length2 = array.GetLength(1);
			T[,] array2 = new T[newSize, length2];
			int num = 0;
			while (num < newSize && num < length)
			{
				for (int i = 0; i < length2; i++)
				{
					array2[num, i] = array[num, i];
				}
				num++;
			}
			array = array2;
		}

		// Token: 0x060018EF RID: 6383 RVA: 0x00421448 File Offset: 0x0041F648
		internal unsafe static void ResizeArrays(bool unloading = false)
		{
			Array.Resize<bool>(ref Main.wallLoaded, WallLoader.nextWall);
			for (int i = 231; i < WallLoader.nextWall; i++)
			{
				Main.wallLoaded[i] = true;
			}
			WallLoader.Resize2DArray<RenderTarget2D>(ref Main.wallAltTexture, WallLoader.nextWall);
			WallLoader.Resize2DArray<bool>(ref Main.wallAltTextureInit, WallLoader.nextWall);
			WallLoader.Resize2DArray<bool>(ref Main.wallAltTextureDrawn, WallLoader.nextWall);
			Array.Resize<Texture2D>(ref Main.wallTexture, WallLoader.nextWall);
			Array.Resize<bool>(ref Main.wallHouse, WallLoader.nextWall);
			Array.Resize<bool>(ref Main.wallDungeon, WallLoader.nextWall);
			Array.Resize<bool>(ref Main.wallLight, WallLoader.nextWall);
			Array.Resize<int>(ref Main.wallBlend, WallLoader.nextWall);
			Array.Resize<byte>(ref Main.wallLargeFrames, WallLoader.nextWall);
			Array.Resize<byte>(ref Main.wallFrame, WallLoader.nextWall);
			Array.Resize<byte>(ref Main.wallFrameCounter, WallLoader.nextWall);
			Array.Resize<bool>(ref WallID.Sets.Conversion.Grass, WallLoader.nextWall);
			Array.Resize<bool>(ref WallID.Sets.Conversion.Stone, WallLoader.nextWall);
			Array.Resize<bool>(ref WallID.Sets.Conversion.Sandstone, WallLoader.nextWall);
			Array.Resize<bool>(ref WallID.Sets.Conversion.HardenedSand, WallLoader.nextWall);
			Array.Resize<bool>(ref WallID.Sets.Transparent, WallLoader.nextWall);
			Array.Resize<bool>(ref WallID.Sets.Corrupt, WallLoader.nextWall);
			Array.Resize<bool>(ref WallID.Sets.Crimson, WallLoader.nextWall);
			Array.Resize<bool>(ref WallID.Sets.Hallow, WallLoader.nextWall);
			ModLoader.BuildGlobalHook<GlobalWall, Func<int, int, int, bool>>(ref WallLoader.HookKillSound, WallLoader.globalWalls, (GlobalWall g) => (Func<int, int, int, bool>)Delegate.CreateDelegate(typeof(Func<int, int, int, bool>), g, methodof(GlobalWall.KillSound(int, int, int))));
			ModLoader.BuildGlobalHook<GlobalWall, WallLoader.DelegateNumDust>(ref WallLoader.HookNumDust, WallLoader.globalWalls, (GlobalWall g) => (WallLoader.DelegateNumDust)Delegate.CreateDelegate(typeof(WallLoader.DelegateNumDust), g, methodof(GlobalWall.NumDust(int, int, int, bool, int*))));
			ModLoader.BuildGlobalHook<GlobalWall, WallLoader.DelegateCreateDust>(ref WallLoader.HookCreateDust, WallLoader.globalWalls, (GlobalWall g) => (WallLoader.DelegateCreateDust)Delegate.CreateDelegate(typeof(WallLoader.DelegateCreateDust), g, methodof(GlobalWall.CreateDust(int, int, int, int*))));
			ModLoader.BuildGlobalHook<GlobalWall, WallLoader.DelegateDrop>(ref WallLoader.HookDrop, WallLoader.globalWalls, (GlobalWall g) => (WallLoader.DelegateDrop)Delegate.CreateDelegate(typeof(WallLoader.DelegateDrop), g, methodof(GlobalWall.Drop(int, int, int, int*))));
			ModLoader.BuildGlobalHook<GlobalWall, WallLoader.DelegateKillWall>(ref WallLoader.HookKillWall, WallLoader.globalWalls, (GlobalWall g) => (WallLoader.DelegateKillWall)Delegate.CreateDelegate(typeof(WallLoader.DelegateKillWall), g, methodof(GlobalWall.KillWall(int, int, int, bool*))));
			ModLoader.BuildGlobalHook<GlobalWall, Func<int, int, int, bool>>(ref WallLoader.HookCanExplode, WallLoader.globalWalls, (GlobalWall g) => (Func<int, int, int, bool>)Delegate.CreateDelegate(typeof(Func<int, int, int, bool>), g, methodof(GlobalWall.CanExplode(int, int, int))));
			ModLoader.BuildGlobalHook<GlobalWall, WallLoader.DelegateModifyLight>(ref WallLoader.HookModifyLight, WallLoader.globalWalls, (GlobalWall g) => (WallLoader.DelegateModifyLight)Delegate.CreateDelegate(typeof(WallLoader.DelegateModifyLight), g, methodof(GlobalWall.ModifyLight(int, int, int, float*, float*, float*))));
			ModLoader.BuildGlobalHook<GlobalWall, Action<int, int, int>>(ref WallLoader.HookRandomUpdate, WallLoader.globalWalls, (GlobalWall g) => (Action<int, int, int>)Delegate.CreateDelegate(typeof(Action<int, int, int>), g, methodof(GlobalWall.RandomUpdate(int, int, int))));
			ModLoader.BuildGlobalHook<GlobalWall, Func<int, int, int, SpriteBatch, bool>>(ref WallLoader.HookPreDraw, WallLoader.globalWalls, (GlobalWall g) => (Func<int, int, int, SpriteBatch, bool>)Delegate.CreateDelegate(typeof(Func<int, int, int, SpriteBatch, bool>), g, methodof(GlobalWall.PreDraw(int, int, int, SpriteBatch))));
			ModLoader.BuildGlobalHook<GlobalWall, Action<int, int, int, SpriteBatch>>(ref WallLoader.HookPostDraw, WallLoader.globalWalls, (GlobalWall g) => (Action<int, int, int, SpriteBatch>)Delegate.CreateDelegate(typeof(Action<int, int, int, SpriteBatch>), g, methodof(GlobalWall.PostDraw(int, int, int, SpriteBatch))));
			ModLoader.BuildGlobalHook<GlobalWall, Action<int, int, int, Item>>(ref WallLoader.HookPlaceInWorld, WallLoader.globalWalls, (GlobalWall g) => (Action<int, int, int, Item>)Delegate.CreateDelegate(typeof(Action<int, int, int, Item>), g, methodof(GlobalWall.PlaceInWorld(int, int, int, Item))));
			if (!unloading)
			{
				WallLoader.loaded = true;
			}
		}

		// Token: 0x060018F0 RID: 6384 RVA: 0x00012306 File Offset: 0x00010506
		internal static void Unload()
		{
			WallLoader.loaded = false;
			WallLoader.walls.Clear();
			WallLoader.nextWall = 231;
			WallLoader.globalWalls.Clear();
		}

		// Token: 0x060018F1 RID: 6385 RVA: 0x0001232C File Offset: 0x0001052C
		internal static void WriteType(ushort wall, byte[] data, ref int index, ref byte flags)
		{
			if (wall > 255)
			{
				data[index] = (byte)(wall >> 8);
				index++;
				flags |= 32;
			}
		}

		// Token: 0x060018F2 RID: 6386 RVA: 0x0001234C File Offset: 0x0001054C
		internal static void ReadType(ref ushort wall, BinaryReader reader, byte flags, IDictionary<int, int> wallTable)
		{
			if ((flags & 32) == 32)
			{
				wall |= (ushort)(reader.ReadByte() << 8);
			}
			if (wallTable.ContainsKey((int)wall))
			{
				wall = (ushort)wallTable[(int)wall];
			}
		}

		// Token: 0x060018F3 RID: 6387 RVA: 0x00421C70 File Offset: 0x0041FE70
		public static bool KillSound(int i, int j, int type)
		{
			foreach (Func<int, int, int, bool> func in WallLoader.HookKillSound)
			{
				if (!func(i, j, type))
				{
					return false;
				}
			}
			ModWall wall = WallLoader.GetWall(type);
			if (wall == null)
			{
				return true;
			}
			if (!wall.KillSound(i, j))
			{
				return false;
			}
			Main.PlaySound(wall.soundType, i * 16, j * 16, wall.soundStyle, 1f, 0f);
			return false;
		}

		// Token: 0x060018F4 RID: 6388 RVA: 0x00421CE0 File Offset: 0x0041FEE0
		public static void NumDust(int i, int j, int type, bool fail, ref int numDust)
		{
			ModWall wall = WallLoader.GetWall(type);
			if (wall != null)
			{
				wall.NumDust(i, j, fail, ref numDust);
			}
			foreach (WallLoader.DelegateNumDust delegateNumDust in WallLoader.HookNumDust)
			{
				delegateNumDust(i, j, type, fail, ref numDust);
			}
		}

		// Token: 0x060018F5 RID: 6389 RVA: 0x00421D28 File Offset: 0x0041FF28
		public static bool CreateDust(int i, int j, int type, ref int dustType)
		{
			foreach (WallLoader.DelegateCreateDust delegateCreateDust in WallLoader.HookCreateDust)
			{
				if (!delegateCreateDust(i, j, type, ref dustType))
				{
					return false;
				}
			}
			ModWall wall = WallLoader.GetWall(type);
			return wall == null || wall.CreateDust(i, j, ref dustType);
		}

		// Token: 0x060018F6 RID: 6390 RVA: 0x00421D70 File Offset: 0x0041FF70
		public static bool Drop(int i, int j, int type, ref int dropType)
		{
			foreach (WallLoader.DelegateDrop delegateDrop in WallLoader.HookDrop)
			{
				if (!delegateDrop(i, j, type, ref dropType))
				{
					return false;
				}
			}
			ModWall wall = WallLoader.GetWall(type);
			return wall == null || wall.Drop(i, j, ref dropType);
		}

		// Token: 0x060018F7 RID: 6391 RVA: 0x00421DB8 File Offset: 0x0041FFB8
		public static void KillWall(int i, int j, int type, ref bool fail)
		{
			ModWall wall = WallLoader.GetWall(type);
			if (wall != null)
			{
				wall.KillWall(i, j, ref fail);
			}
			foreach (WallLoader.DelegateKillWall delegateKillWall in WallLoader.HookKillWall)
			{
				delegateKillWall(i, j, type, ref fail);
			}
		}

		// Token: 0x060018F8 RID: 6392 RVA: 0x00421DFC File Offset: 0x0041FFFC
		public static bool CanExplode(int i, int j, int type)
		{
			foreach (Func<int, int, int, bool> func in WallLoader.HookCanExplode)
			{
				if (!func(i, j, type))
				{
					return false;
				}
			}
			ModWall wall = WallLoader.GetWall(type);
			return wall == null || wall.CanExplode(i, j);
		}

		// Token: 0x060018F9 RID: 6393 RVA: 0x00421E44 File Offset: 0x00420044
		public static void ModifyLight(int i, int j, int type, ref float r, ref float g, ref float b)
		{
			ModWall wall = WallLoader.GetWall(type);
			if (wall != null)
			{
				wall.ModifyLight(i, j, ref r, ref g, ref b);
			}
			foreach (WallLoader.DelegateModifyLight delegateModifyLight in WallLoader.HookModifyLight)
			{
				delegateModifyLight(i, j, type, ref r, ref g, ref b);
			}
		}

		// Token: 0x060018FA RID: 6394 RVA: 0x00421E90 File Offset: 0x00420090
		public static void RandomUpdate(int i, int j, int type)
		{
			ModWall wall = WallLoader.GetWall(type);
			if (wall != null)
			{
				wall.RandomUpdate(i, j);
			}
			foreach (Action<int, int, int> action in WallLoader.HookRandomUpdate)
			{
				action(i, j, type);
			}
		}

		// Token: 0x060018FB RID: 6395 RVA: 0x00421ED4 File Offset: 0x004200D4
		public static void AnimateWalls()
		{
			if (WallLoader.loaded)
			{
				for (int i = 0; i < WallLoader.walls.Count; i++)
				{
					ModWall modWall = WallLoader.walls[i];
					modWall.AnimateWall(ref Main.wallFrame[(int)modWall.Type], ref Main.wallFrameCounter[(int)modWall.Type]);
				}
			}
		}

		// Token: 0x060018FC RID: 6396 RVA: 0x00421F30 File Offset: 0x00420130
		public static bool PreDraw(int i, int j, int type, SpriteBatch spriteBatch)
		{
			foreach (Func<int, int, int, SpriteBatch, bool> func in WallLoader.HookPreDraw)
			{
				if (!func(i, j, type, spriteBatch))
				{
					return false;
				}
			}
			ModWall wall = WallLoader.GetWall(type);
			return wall == null || wall.PreDraw(i, j, spriteBatch);
		}

		// Token: 0x060018FD RID: 6397 RVA: 0x00421F78 File Offset: 0x00420178
		public static void PostDraw(int i, int j, int type, SpriteBatch spriteBatch)
		{
			ModWall wall = WallLoader.GetWall(type);
			if (wall != null)
			{
				wall.PostDraw(i, j, spriteBatch);
			}
			foreach (Action<int, int, int, SpriteBatch> action in WallLoader.HookPostDraw)
			{
				action(i, j, type, spriteBatch);
			}
		}

		// Token: 0x060018FE RID: 6398 RVA: 0x00421FBC File Offset: 0x004201BC
		public static void PlaceInWorld(int i, int j, Item item)
		{
			int createWall = item.createWall;
			if (createWall < 0)
			{
				return;
			}
			foreach (Action<int, int, int, Item> action in WallLoader.HookPlaceInWorld)
			{
				action(i, j, createWall, item);
			}
			ModWall wall = WallLoader.GetWall(createWall);
			if (wall == null)
			{
				return;
			}
			wall.PlaceInWorld(i, j, item);
		}

		// Token: 0x040016DF RID: 5855
		private static int nextWall = 231;

		// Token: 0x040016E0 RID: 5856
		internal static readonly IList<ModWall> walls = new List<ModWall>();

		// Token: 0x040016E1 RID: 5857
		internal static readonly IList<GlobalWall> globalWalls = new List<GlobalWall>();

		// Token: 0x040016E2 RID: 5858
		private static bool loaded = false;

		// Token: 0x040016E3 RID: 5859
		private static Func<int, int, int, bool>[] HookKillSound;

		// Token: 0x040016E4 RID: 5860
		private static WallLoader.DelegateNumDust[] HookNumDust;

		// Token: 0x040016E5 RID: 5861
		private static WallLoader.DelegateCreateDust[] HookCreateDust;

		// Token: 0x040016E6 RID: 5862
		private static WallLoader.DelegateDrop[] HookDrop;

		// Token: 0x040016E7 RID: 5863
		private static WallLoader.DelegateKillWall[] HookKillWall;

		// Token: 0x040016E8 RID: 5864
		private static Func<int, int, int, bool>[] HookCanExplode;

		// Token: 0x040016E9 RID: 5865
		private static WallLoader.DelegateModifyLight[] HookModifyLight;

		// Token: 0x040016EA RID: 5866
		private static Action<int, int, int>[] HookRandomUpdate;

		// Token: 0x040016EB RID: 5867
		private static Func<int, int, int, SpriteBatch, bool>[] HookPreDraw;

		// Token: 0x040016EC RID: 5868
		private static Action<int, int, int, SpriteBatch>[] HookPostDraw;

		// Token: 0x040016ED RID: 5869
		private static Action<int, int, int, Item>[] HookPlaceInWorld;

		// Token: 0x02000254 RID: 596
		// (Invoke) Token: 0x06001901 RID: 6401
		private delegate void DelegateNumDust(int i, int j, int type, bool fail, ref int num);

		// Token: 0x02000255 RID: 597
		// (Invoke) Token: 0x06001905 RID: 6405
		private delegate bool DelegateCreateDust(int i, int j, int type, ref int dustType);

		// Token: 0x02000256 RID: 598
		// (Invoke) Token: 0x06001909 RID: 6409
		private delegate bool DelegateDrop(int i, int j, int type, ref int dropType);

		// Token: 0x02000257 RID: 599
		// (Invoke) Token: 0x0600190D RID: 6413
		private delegate void DelegateKillWall(int i, int j, int type, ref bool fail);

		// Token: 0x02000258 RID: 600
		// (Invoke) Token: 0x06001911 RID: 6417
		private delegate void DelegateModifyLight(int i, int j, int type, ref float r, ref float g, ref float b);
	}
}
